<?xml version="1.0"?>
<local:ViewBase xmlns:f="library://ns.feathersui.com/mxml" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:local="*"
                creationComplete="onCreationComplete()">

    <local:layout>
        <f:VerticalLayout gap="15" horizontalAlign="center" padding="25"/>
    </local:layout>

    <f:LayoutGroup>
        <f:layout>
            <f:HorizontalLayout gap="10" verticalAlign="middle"/>
        </f:layout>
        <f:Label text="Login:" minWidth="80"/>
        <f:TextInput id="loginInput" minWidth="150"/>
    </f:LayoutGroup>

    <f:LayoutGroup>
        <f:layout>
            <f:HorizontalLayout gap="10" verticalAlign="middle"/>
        </f:layout>
        <f:Label text="Password:" minWidth="80"/>
        <f:TextInput id="passwordInput" minWidth="150"/>
    </f:LayoutGroup>

    <f:LayoutGroup>
        <f:layout>
            <f:HorizontalLayout gap="10" verticalAlign="middle"/>
        </f:layout>
        <f:Label text="Scores:" minWidth="80"/>
        <f:TextInput id="scoresInput" minWidth="150"/>
    </f:LayoutGroup>

    <f:Button label="Register" triggered="onRegister()"/>

    <f:Button label="Get data" triggered="onGetData()"/>

    <f:Button label="Set data" triggered="onSetData()"/>

    <fx:Script><![CDATA[
        import com.adobe.crypto.MD5;
        import com.sociodox.utils.Base64;

        import flash.events.Event;
        import flash.events.IOErrorEvent;
        import flash.events.SecurityErrorEvent;

        import starling.core.Starling;

        import starling.utils.StringUtil;

        private static const URL:String = "http://127.0.0.1:8000/";
//        private static const URL:String = "http://vcow.pythonanywhere.com/";

        private var _loaders:Vector.<URLLoader> = new Vector.<URLLoader>();

        private function onGetData():void
        {
            getData();
        }

        private function onSetData():void
        {
            setData();
        }

        private function onRegister():void
        {
            register();
        }

        private function onCreationComplete():void
        {
            URLRequestDefaults.authenticate = false;
            URLRequestDefaults.cacheResponse = false;
            URLRequestDefaults.useCache = false;
        }

        private function getData():void
        {
            send(URL + "data/get/", null);
        }

        private function register():void
        {
            var variables:URLVariables = new URLVariables();
            variables.username = StringUtil.trim(loginInput.text).slice(0, 12);
            variables.password = passwordInput.text.slice(0, 50);
            send(URL + "data/register/", variables);
        }

        private function auth():void
        {
            var variables:URLVariables = new URLVariables();
            variables.username = StringUtil.trim(loginInput.text).slice(0, 12);
            variables.password = passwordInput.text.slice(0, 50);
            send(URL + "data/auth/", variables);
        }

        private function setData():void
        {
            var scores:Number = Number(scoresInput.text);
            var scoresText:String = (isNaN(scores) ? 0 : Math.floor(scores)).toString();
            var variables:URLVariables = new URLVariables();
            var data:Object = {
                scores: encode(scoresText)
            };
            variables.data = JSON.stringify(data);
            send(URL + "data/set/", variables);
        }

        private static function encode(msg:String):String
        {
            var buffer1:ByteArray = new ByteArray();
            buffer1.writeUTFBytes(msg);
            for (var i:int = 0, l:int = buffer1.length % 4; i < l; i++) buffer1.writeByte(0);
            buffer1.position = 0;
            var buffer2:ByteArray = new ByteArray();
            while (buffer1.bytesAvailable)
            {
                var chunk:uint = buffer1.readUnsignedInt() ^ 0xe6eeefe0;
                buffer2.writeUnsignedInt(chunk);
            }
            buffer2.position = 0;
            var md5:String = MD5.hash(msg);
            buffer1.clear();
            buffer1.writeUTFBytes(md5);
            buffer1.writeInt(msg.length);
            buffer1.writeBytes(buffer2);
            buffer1.position = 0;
            return Base64.encode(buffer1);
        }

        private function send(url:String, data:URLVariables):void
        {
            Starling.current.stage.touchable = false;
            var loader:URLLoader = new URLLoader();
            loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
            loader.addEventListener(flash.events.Event.COMPLETE, onComplete);
            var request:URLRequest = new URLRequest(url);
            request.data = data;
            loader.load(request);
            _loaders.push(loader);
        }

        private function onError(event:flash.events.Event):void
        {
            Starling.current.stage.touchable = true;
            removeLoader(event.target as URLLoader);
            trace(event["text"]);
        }

        private function onComplete(event:flash.events.Event):void
        {
            Starling.current.stage.touchable = true;
            var loader:URLLoader = removeLoader(event.target as URLLoader);
            var data:String = String(loader.data);
            try {
                processResponse(JSON.parse(data));
            }
            catch (e:Error) {
                processResponse({error: "unexpected"});
            }
        }

        private function processResponse(response:Object):void
        {
            if (response.hasOwnProperty("error"))
            {
                switch (response.error.toLowerCase())
                {
                    case "not registered":
                        register();
                        break;
                    case "not authenticated":
                        auth();
                        break;
                    case "already registered":
                        setData();
                        break;
                }
            }
            else if (response.hasOwnProperty("cmd"))
            {
                switch (response.cmd)
                {
                    case "register":
                        auth();
                        break;
                    case "auth":
                        setData();
                        break;
                    case "set":
                        loginInput.text = "";
                        passwordInput.text = "";
                        scoresInput.text = Math.floor(Math.random() * 10000000000.0).toString();
                        break;
                }
            }
        }

        private function removeLoader(loader:URLLoader):URLLoader
        {
            var index:int = _loaders.indexOf(loader);
            if (index != -1)
            {
                _loaders.splice(index, 1);
                loader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
                loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
                loader.removeEventListener(flash.events.Event.COMPLETE, onComplete);
            }
            return loader;
        }
        ]]></fx:Script>
</local:ViewBase>